/* SPDX-License-Identifier: GPL-2.0 */

#ifndef __QUICK_KEXEC_INTERNAL_H
#define __QUICK_KEXEC_INTERNAL_H

#include <linux/types.h>

#ifdef CONFIG_QUICK_KEXEC
#define SHA256_DIGEST_SIZE 32
#define KEXEC_MAX_EXTEND_RES_NUM 5
#define RES_NAME_MAX_LEN 16
struct kexec_extend_res_area {
	char res_name[RES_NAME_MAX_LEN];
	unsigned long start;
	unsigned long end;
};
struct kexec_extend_res {
	unsigned long magic;
	unsigned char digest[SHA256_DIGEST_SIZE];
	unsigned int res_num;
	struct kexec_extend_res_area area[KEXEC_MAX_EXTEND_RES_NUM];
};

#ifdef CONFIG_EULEROS_ANGEL_CORE_MONITOR
struct kup_monitor_operations {
	unsigned int (*kup_monitor_core_show)(void);
	int (*kup_monitor_core_store)(unsigned int cpu);
	unsigned int (*kup_monitor_timeout_show)(void);
	int (*kup_monitor_timeout_store)(unsigned int timeout);
};
#endif

#define KEXEC_START_ENTRY_OFFSET (SHA256_DIGEST_SIZE + sizeof(unsigned long))
#define KEXEC_ROLLBACK   0x00000020
#define KEXEC_EXTEND_RES_MAGIC  0xEDB88880
#define QUICK_ROLLBACK_RES_NAME "Quick rollback"
#define ANGEL_MONITOR_RES_NAME "Angel monitor"
#define CPU_PARK_RES_NAME "SMP Park space"
#define KEXEC_RES_RESTORE_NUM  3
#define QUICK_ROLLBACK_MAGIC  0xED387650
#define ROLL_BACK_IMAGE_OFFSET  0x2000
#define KEXEC_EXTEND_RES_SIZE   0x2000

#define DEFAULT_KEXEC_ROLLBACK_TIMEOUT_MS	3000

#if (defined CONFIG_X86) && (defined CONFIG_QUICK_KEXEC)
#define KEXC_FILE_LOAD_INITRD_INDEX	3
#define SEGMENT_INITRD_INDEX_OFFSET	3
#else
#define KEXC_FILE_LOAD_INITRD_INDEX	1
#define SEGMENT_INITRD_INDEX_OFFSET	2
#endif /* (defined CONFIG_X86) && (defined CONFIG_QUICK_KEXEC) */

#define RES_START_OFFSET  1024
#define MAX_QUICK_KEXEC_REGIONS 4
#define KEXEC_RES_NUM_OFFSET (SHA256_DIGEST_SIZE + sizeof(unsigned long))

extern bool kexec_panic_rollback;

#ifdef CONFIG_EULEROS_ANGEL_CORE_MONITOR
extern void register_kup_monitor_operations(struct kup_monitor_operations *ops);
#endif
extern int is_kexec_extend_res_ready(void);
extern struct resource *get_kexec_extend_res(char *res_name);
extern int __init quick_rollback_init(void);
extern int __init get_kexec_extend_res_space(struct resource **res);
extern void __init free_kexec_extend_res_space(void);
extern void __init restore_kexec_extend_res(u64 res_start);
extern bool is_kexec_restore_res_enable(void);
extern bool is_kexec_restore_succ(void);
extern void set_quick_rollback_ability(int is_enable);
extern bool has_quick_rollback_ability(void);
extern bool is_quick_rollback_enable(void);
extern int quick_kernel_kexec(void);
extern void try_rollback(void);
extern void boot_try_rollback(void);
extern int check_quick_kexec_segment(struct kimage *image,
		unsigned long res_start, unsigned long res_end);
extern void generate_sha_digest(const unsigned char *string,
		unsigned long size, unsigned char *digest);
extern int save_rollback_file_image_state(int kernel_fd, int initrd_fd,
			unsigned long cmdline_len, const char __user *cmdline_ptr,
			unsigned long flags);
extern int fill_kexec_extend_res(void *start, unsigned int is_rollback_segments);
extern void set_kexec_extend_res_ready(void);
extern int increase_memmap_items(char *cmdline, size_t len);
#ifdef CONFIG_X86
extern int do_modify_cmdline(struct boot_params *boot_params, size_t size);
extern void skip_kexecmem_cmd(char *cmdline);
#else
extern int do_modify_cmdline(void *boot_params, size_t size);
static inline void skip_kexecmem_cmd(char *cmdline) {}
#endif

extern bool is_smp_init_finished(void);
extern void set_smp_init_finished(bool init_finished);

extern void request_kexec_extend_res(struct resource *res);
#else

static inline void request_kexec_extend_res(struct resource *res) {}
#endif /* CONFIG_QUICK_KEXEC */

#if defined(CONFIG_EULEROS_ANGEL_CORE_MONITOR) && defined(CONFIG_ARM64)
extern int kexec_rollback_nmicallback(void);
#endif

static inline struct resource *get_quick_kexec_res(void) { return NULL; }
static inline struct resource *get_quick_rollback_res(void) { return NULL; }
static inline void set_quick_rollback_res(struct resource *res) {}
//static inline int exit_irq_ctx(void) { return 0; }
static inline void panic_irq_exit(void) {}
//static inline void irq_kexec_ctx(void *arg) {}
static inline void fixup_pmuevent(void) {}
static inline int fixup_hrtimer(void) { return 0; }
//static inline void try_rollback(void) {}
static inline bool try_own_printk_locks(void) { return true; }
static inline bool try_own_safe_printk_locks(void) { return true; }

#ifdef CONFIG_EULEROS_ANGEL_CORE_MONITOR
#define INVALID_ANGEL_CORE  0xffffffff
extern bool is_angel_core(unsigned int cpu);
extern bool has_angel_core(void);
extern unsigned int get_angel_core(void);
extern void set_angel_core(unsigned int cpu);
extern unsigned int get_angel_core_event(void);
extern void set_angel_core_event(unsigned int *addr);
extern void clear_angel_core_event(void);

extern unsigned long get_last_angel_timeout(void);
extern void set_last_angel_timeout(unsigned long timeout);

#ifdef CONFIG_X86
extern int quick_rollback_handler(unsigned int cmd, struct pt_regs *regs);
#else
static inline int quick_rollback_handler(unsigned int cmd, struct pt_regs *regs) { return 0; }
#endif
#endif /* CONFIG_EULEROS_ANGEL_CORE_MONITOR */
#endif /* ifndef __QUICK_KEXEC_INTERNAL_H */

